﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Text;
using System.Windows;
using FluentValidation.Results;
using Microsoft.Win32;

namespace LINQPad.OpenAccess.UI.Services
{
    /// <summary>
    /// <see cref="IUserInteractionService"/>
    /// </summary>
    public class UserInteractionService : IUserInteractionService
    {
        #region Private

        #region - Vars

        [DebuggerBrowsable( DebuggerBrowsableState.Never )]
        private string _defaultInitialDirectory;

        #endregion

        #region - Functions

        /// <summary>
        /// Creates the open file dialog.
        /// </summary>
        /// <param name="title">The title.</param>
        /// <param name="defaultExt">The default ext.</param>
        /// <param name="filter">The filter.</param>
        /// <param name="filterIndex">Index of the filter.</param>
        /// <returns>The dialog.</returns>
        private OpenFileDialog CreateOpenFileDialog( string title, string defaultExt, string filter = null, int filterIndex = 0 )
        {
            var dialog = new OpenFileDialog( );
            dialog.Title = title;
            dialog.DefaultExt = defaultExt;
            if ( !String.IsNullOrWhiteSpace( filter ) )
            {
                dialog.Filter = filter;
                dialog.FilterIndex = filterIndex;
            }
            dialog.InitialDirectory = this._defaultInitialDirectory ?? Environment.CurrentDirectory;
            dialog.AddExtension = true;
            dialog.CheckFileExists = true;
            return dialog;
        }
        /// <summary>
        /// Sets the default initial directory.
        /// </summary>
        /// <param name="filePath">The file path.</param>
        private void SetDefaultInitialDirectory( string filePath )
        {
            if ( filePath == null )
                this._defaultInitialDirectory = null;
            else
                this._defaultInitialDirectory = Path.GetDirectoryName( filePath );
        }

        #endregion

        #endregion

        #region IUserInteractionService Members

        /// <summary>
        /// Shows the 'cannot save due to validation errors' notification.
        /// </summary>
        /// <param name="validationFailures">The validation failures.</param>
        public void ShowCannotSaveDueToValidationErrorsNotification( IList<ValidationFailure> validationFailures )
        {
            var sb = new StringBuilder( );
            sb.AppendLine( "Cannot save due to validation errors !" );
            if ( validationFailures != null && validationFailures.Count > 0 )
            {
                foreach ( var failure in validationFailures )
                    sb.AppendFormat( " - {0}\n", failure.ErrorMessage );
            }

            MessageBox.Show( sb.ToString( ), "Error", MessageBoxButton.OK, MessageBoxImage.Exclamation );
        }
        /// <summary>
        /// Shows the connection test failed notification.
        /// </summary>
        /// <param name="exception">The exception.</param>
        public void ShowConnectionTestFailedNotification( Exception exception )
        {
            string message = "Connection failed !";
            if ( exception != null )
            {
                message = String.Format( "{0}\n\nReason:\n{1}", message, exception.Message );
                if ( exception.GetBaseException( ).Message != exception.Message )
                    message = String.Format( "{0}\n--\n{1}", message, exception.GetBaseException( ).Message );
            }
            MessageBox.Show( message, "Connection Test", MessageBoxButton.OK, MessageBoxImage.Warning );
        }
        /// <summary>
        /// Shows the connection test succeeded notification.
        /// </summary>
        public void ShowConnectionTestSucceededNotification( )
        {
            MessageBox.Show( "Connection successful", "Connection Test", MessageBoxButton.OK, MessageBoxImage.Information );
        }
        /// <summary>
        /// Called to choose the app config for an open access context.
        /// </summary>
        /// <param name="appConfigFilePath">The app config file path.</param>
        /// <returns>
        ///   <c>true</c> on success; otherwise, <c>false</c>.
        /// </returns>
        /// <exception cref="System.NotImplementedException"></exception>
        public bool TryChooseAppConfig( out string appConfigFilePath )
        {
            var dialog = this.CreateOpenFileDialog( "Choose app config", ".config", "Application config files (*.config)|*.config" );
            dialog.AddExtension = false;
            dialog.CheckFileExists = false;

            if ( dialog.ShowDialog( ).GetValueOrDefault( ) )
            {
                appConfigFilePath = dialog.FileName;
                this.SetDefaultInitialDirectory( dialog.FileName );
                return true;
            }

            appConfigFilePath = null;
            return false;
        }
        /// <summary>
        /// Called to choose the assembly of the open access context.
        /// </summary>
        /// <param name="assemblyFilePath">The assembly file path.</param>
        /// <returns>
        ///   <c>true</c> on success; otherwise, <c>false</c>.
        /// </returns>
        public bool TryChooseAssembly( out string assemblyFilePath )
        {
            var dialog = this.CreateOpenFileDialog( "Choose assembly", ".dll", "Dll Files (*.dll)|*.dll|Executables|*.exe" );

            if ( dialog.ShowDialog( ).GetValueOrDefault( ) )
            {
                assemblyFilePath = dialog.FileName;
                this.SetDefaultInitialDirectory( dialog.FileName );
                return true;
            }

            assemblyFilePath = null;
            return false;
        }
        #endregion
    }
}
